/*
    虚拟机管理模块测试
*/

#include <gtest/gtest.h>
#include "../../src/server/virtual_host.hpp"

class VirtualHostTest : public testing::Test
{
public:
    virtual void SetUp() override
    {
        _virtual_host_ptr = std::make_shared<mq::VirtualHost>("virtual_host_1", "test.db", "durable_msg_file_dir");
        google::protobuf::Map<std::string, std::string> args;
        _virtual_host_ptr->declareExchanger("exchanger_1", mq::ExchangerType::DIRECT, true, false, args);
        _virtual_host_ptr->declareExchanger("exchanger_2", mq::ExchangerType::DIRECT, true, false, args);
        _virtual_host_ptr->declareExchanger("exchanger_3", mq::ExchangerType::DIRECT, true, false, args);
        _virtual_host_ptr->declareMsgQueue("queue_1", true, false, false, {});
        _virtual_host_ptr->declareMsgQueue("queue_2", true, false, false, {});
        _virtual_host_ptr->declareMsgQueue("queue_3", true, false, false, {});

        _virtual_host_ptr->bind("exchanger_1", "queue_1", "news.musics.*");
        _virtual_host_ptr->bind("exchanger_1", "queue_2", "news.musics.*");
        _virtual_host_ptr->bind("exchanger_1", "queue_3", "news.musics.*");

        _virtual_host_ptr->bind("exchanger_2", "queue_1", "news.musics.*");
        _virtual_host_ptr->bind("exchanger_2", "queue_2", "news.musics.*");
        _virtual_host_ptr->bind("exchanger_2", "queue_3", "news.musics.*");

        _virtual_host_ptr->bind("exchanger_3", "queue_1", "news.musics.*");
        _virtual_host_ptr->bind("exchanger_3", "queue_2", "news.musics.*");
        _virtual_host_ptr->bind("exchanger_3", "queue_3", "news.musics.*");

        _virtual_host_ptr->publish("queue_1", nullptr, "hello world 1");
        _virtual_host_ptr->publish("queue_1", nullptr, "hello world 2");
        _virtual_host_ptr->publish("queue_1", nullptr, "hello world 3");

        _virtual_host_ptr->publish("queue_2", nullptr, "hello world 1");
        _virtual_host_ptr->publish("queue_2", nullptr, "hello world 2");
        _virtual_host_ptr->publish("queue_2", nullptr, "hello world 3");

        _virtual_host_ptr->publish("queue_3", nullptr, "hello world 1");
        _virtual_host_ptr->publish("queue_3", nullptr, "hello world 2");
        _virtual_host_ptr->publish("queue_3", nullptr, "hello world 3");
    }

    virtual void TearDown() override // 在每一个相关的测试函数执行后，进行数据的清理
    {
        _virtual_host_ptr->clear();
    }


public:
    mq::VirtualHost::VirtualHostPtr _virtual_host_ptr;
};

TEST_F(VirtualHostTest, init_test)
{
    EXPECT_EQ(_virtual_host_ptr->hasExchanger("exchanger_1"), true);
    EXPECT_EQ(_virtual_host_ptr->hasExchanger("exchanger_2"), true);
    EXPECT_EQ(_virtual_host_ptr->hasExchanger("exchanger_3"), true);
    EXPECT_EQ(_virtual_host_ptr->hasMsgQueue("queue_1"), true);
    EXPECT_EQ(_virtual_host_ptr->hasMsgQueue("queue_2"), true);
    EXPECT_EQ(_virtual_host_ptr->hasMsgQueue("queue_3"), true);

    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_1", "queue_1"), true);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_1", "queue_2"), true);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_1", "queue_3"), true);
    
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_2", "queue_1"), true);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_2", "queue_2"), true);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_2", "queue_3"), true);

    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_3", "queue_1"), true);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_3", "queue_2"), true);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_3", "queue_3"), true);

}

TEST_F(VirtualHostTest, remove_test)
{
    _virtual_host_ptr->removeExchanger("exchanger_1");
    EXPECT_EQ(_virtual_host_ptr->hasExchanger("exchanger_1"), false);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_1", "queue_1"), false);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_1", "queue_2"), false);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_1", "queue_3"), false);

    _virtual_host_ptr->removeMsgQueue("queue_1");
    EXPECT_EQ(_virtual_host_ptr->hasMsgQueue("queue_1"), false);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_1", "queue_1"), false);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_2", "queue_1"), false);
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_3", "queue_1"), false);


    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_2", "queue_2"), true);
    _virtual_host_ptr->unbind("exchanger_2", "queue_2");
    EXPECT_EQ(_virtual_host_ptr->hasBinding("exchanger_2", "queue_2"), false);
}

TEST_F(VirtualHostTest, consume_ack_test)
{
    mq::MessagePtr msg_ptr = _virtual_host_ptr->consume("queue_2");
    EXPECT_EQ(msg_ptr->payload().body(), "hello world 1");
    EXPECT_EQ(_virtual_host_ptr->getWaittingAckCnt("queue_2"), 1);
    _virtual_host_ptr->ack("queue_2", msg_ptr->payload().properties().id());
    EXPECT_EQ(_virtual_host_ptr->getWaittingAckCnt("queue_2"), 0);

    msg_ptr = _virtual_host_ptr->consume("queue_2");
    EXPECT_EQ(msg_ptr->payload().body(), "hello world 2");
    EXPECT_EQ(_virtual_host_ptr->getWaittingAckCnt("queue_2"), 1);
    _virtual_host_ptr->ack("queue_2", msg_ptr->payload().properties().id());
    EXPECT_EQ(_virtual_host_ptr->getWaittingAckCnt("queue_2"), 0);

    msg_ptr = _virtual_host_ptr->consume("queue_2");
    EXPECT_EQ(msg_ptr->payload().body(), "hello world 3");
    EXPECT_EQ(_virtual_host_ptr->getWaittingAckCnt("queue_2"), 1);
    _virtual_host_ptr->ack("queue_2", msg_ptr->payload().properties().id());
    EXPECT_EQ(_virtual_host_ptr->getWaittingAckCnt("queue_2"), 0);
}

int main(int argc, char* argv[]) 
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}